//
//  CQHorizontalView.m
//  Pods
//
//  Created by 陈长青 on 2017/4/4.
//
//

#import "CQHorizontalView.h"
#import "NSTimer+Additions.h"

////////////////////////////////////////////////////////////////
// MARK: - 水平视图浏览器
////////////////////////////////////////////////////////////////

@interface CQHorizontalView ()<UIScrollViewDelegate,UIGestureRecognizerDelegate>

// scrollView控件

@property (nonatomic, weak) UIScrollView *scrollView;

// scrollView内部

@property (nonatomic, weak) UIView *scrollViewInner;

// scrollView内部宽

@property (nonatomic, weak) NSLayoutConstraint *scrollViewInnerWidth;

// 上一次控件宽

@property (assign, nonatomic) CGFloat oldWidth;

// 3个 被显示的子视图数组

@property (nonatomic, strong) NSMutableArray<UIView<CQHorizontalViewCellProtocol> *> *horizontalViewCells;

// 准备 被显示的子视图数组(复用)

@property (nonatomic, strong) NSMutableArray<UIView<CQHorizontalViewCellProtocol> *> *readyToUseHorizontalViewCells;

// 子视图左边距字典

@property (nonatomic, strong) NSMutableDictionary *leftMarginDic;

// 导航栏左边距字典

@property (nonatomic, strong) NSMutableDictionary *leftMarginNavDic;

// 导航下边距字典

@property (nonatomic, strong) NSMutableDictionary *topMarginNavDic;

// 底栏左边距字典

@property (nonatomic, strong) NSMutableDictionary *leftMarginToolDic;

// 底栏下边距字典

@property (nonatomic, strong) NSMutableDictionary *bottomMarginToolDic;

// 是否显示导航栏、底栏

@property (nonatomic) BOOL controlsHidden;

// 计时器

@property (strong, nonatomic) NSTimer *timer;

// cell的左边占位视图

@property (nonatomic, strong) NSMutableDictionary *cellLeftPlaceholderViewDic;

@end

@implementation CQHorizontalView

#pragma mark - 生命周期

- (void)awakeFromNib {
    [super awakeFromNib];
    
    [self setup];
}

- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
        
        [self setup];
    }
    return self;
}

- (void)setup {
    
    self.backgroundColor = [UIColor clearColor];
    _controlsHidden = YES;
    
    // scrollView控件
    
    UIScrollView *scrollView = [UIScrollView new];
    
    scrollView.showsVerticalScrollIndicator = false;
    scrollView.showsHorizontalScrollIndicator = false;
    scrollView.pagingEnabled = true;
    scrollView.delegate = self;
    
    [self addSubview:scrollView];
    _scrollView = scrollView;
    
    _scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    NSDictionary *views = NSDictionaryOfVariableBindings(_scrollView);
    
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_scrollView]-0-|" options:nil metrics:nil views:views]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_scrollView]-0-|" options:nil metrics:nil views:views]];
    
    // scrollView内部
    
    UIView *scrollViewInner = [UIView new];
    [_scrollView addSubview:scrollViewInner];
    _scrollViewInner = scrollViewInner;
    
    _scrollViewInner.translatesAutoresizingMaskIntoConstraints = NO;
    views = NSDictionaryOfVariableBindings(_scrollViewInner);
    
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_scrollViewInner]-0-|" options:nil metrics:nil views:views]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_scrollViewInner]-0-|" options:nil metrics:nil views:views]];
    [self addConstraint:[NSLayoutConstraint constraintWithItem:_scrollViewInner attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_scrollView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    
    // 初始化数组、字典
    
    _horizontalViewCells = [NSMutableArray array];
    _readyToUseHorizontalViewCells = [NSMutableArray array];
    _leftMarginDic = [NSMutableDictionary dictionary];
    _leftMarginNavDic = [NSMutableDictionary dictionary];
    _leftMarginToolDic = [NSMutableDictionary dictionary];
    _topMarginNavDic = [NSMutableDictionary dictionary];
    _bottomMarginToolDic = [NSMutableDictionary dictionary];
    _cellLeftPlaceholderViewDic = [NSMutableDictionary dictionary];
    
    // 添加手势事件
    
    UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleControls)];
    tapGes.delegate = self;
    [self addGestureRecognizer:tapGes];
    
    // 添加长按手势
    UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
    recognizer.minimumPressDuration = 0.5; //设置最小长按时间；默认为0.5秒
    [self addGestureRecognizer:recognizer];
    
}

- (void)dealloc {
    
    [_timer invalidate];
    _timer = nil;
    NSLog(@"%s",__FUNCTION__);
}

#pragma mark - 内部方法

- (UIView *)createCellLeftPlaceholderView:(NSInteger) index {
    
    UIView *leftView = [_cellLeftPlaceholderViewDic objectForKey:[NSString stringWithFormat:@"%ld",index]];
    
    if (!leftView) {
        
        leftView = [UIView new];
        leftView.backgroundColor = [UIColor clearColor];
        [_scrollViewInner addSubview:leftView];
        
        [_cellLeftPlaceholderViewDic setObject:leftView forKey:[NSString stringWithFormat:@"%ld",index]];
        
        leftView.translatesAutoresizingMaskIntoConstraints = NO;
        NSDictionary *views = NSDictionaryOfVariableBindings(leftView);
        [_scrollViewInner addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[leftView]-0-|" options:0 metrics:nil views:views]];
        [_scrollViewInner addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[leftView]" options:0 metrics:nil views:views]];
        [self addConstraint:[NSLayoutConstraint constraintWithItem:leftView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:index constant:0]];
        
    }
    return leftView;
    
}

- (void)layoutSubviews {
    [super layoutSubviews];
    [self resetScrollViewInnerWidth];
}


// 重置 scrollView 的 contentSize

- (NSInteger)resetScrollViewInnerWidth {
    
    NSInteger numberOfCells = 0;
    if ([_dataSource respondsToSelector:@selector(numberOfCellsInHorizontalView:)]) {
        
        numberOfCells = [_dataSource numberOfCellsInHorizontalView:self];
    }
    
    if (_scrollViewInnerWidth) {
        
        [self removeConstraint:_scrollViewInnerWidth];
    }
    
    NSLayoutConstraint *scrollViewInnerWidth = [NSLayoutConstraint constraintWithItem:_scrollViewInner attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:_scrollView attribute:NSLayoutAttributeWidth multiplier:numberOfCells constant:0];
    [self addConstraint:scrollViewInnerWidth];
    _scrollViewInnerWidth = scrollViewInnerWidth;
    
    [self layoutIfNeeded];
    
    [_scrollView setContentSize:_scrollViewInner.frame.size];
    NSLog(@"%@",NSStringFromCGRect(_scrollViewInner.frame));
    
    CGFloat width = _scrollViewInner.frame.size.width/numberOfCells;
    [_scrollView setContentOffset:CGPointMake(width*_currentPage, 0)];
    
    return numberOfCells;
}

// 设置cell

- (UIView<CQHorizontalViewCellProtocol> * )setCellForIndex:(NSInteger)index {
    
    [self removeCellToReUse];
    
    // cell
    
    UIView<CQHorizontalViewCellProtocol> * cell;
    NSArray<UIView<CQHorizontalViewCellProtocol> *> *exists = [_horizontalViewCells filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"index == %d", index]];
    if (exists.count==0) {
    
        if ([_dataSource respondsToSelector:@selector(horizontalView:cellForIndex:)]) {
            
            cell = [_dataSource horizontalView:self cellForIndex:index];
            
            if (cell) {
                
                cell.index = index;
                [_scrollViewInner addSubview:cell];
                [_horizontalViewCells addObject:cell];
                
                cell.translatesAutoresizingMaskIntoConstraints = NO;
                NSDictionary *views = NSDictionaryOfVariableBindings(cell);
                [_scrollViewInner addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[cell]-0-|" options:nil metrics:nil views:views]];
                [self addConstraint:[NSLayoutConstraint constraintWithItem:cell attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];
                
                [_scrollViewInner addConstraint:[NSLayoutConstraint constraintWithItem:cell attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:[self createCellLeftPlaceholderView:index] attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]];
                
//                CGFloat leftMargin;
//                if ([_dataSource respondsToSelector:@selector(widthForHorizontalView:)]) {
//                    leftMargin = [_dataSource widthForHorizontalView:self] * index;
//                }
//                NSLayoutConstraint *leftMarginC = [NSLayoutConstraint constraintWithItem:cell  attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_scrollViewInner attribute:NSLayoutAttributeLeft multiplier:1 constant:leftMargin];
                
//                [_scrollViewInner addConstraint:leftMarginC];
                
//                [_leftMarginDic setObject:leftMarginC forKey:[NSString stringWithFormat:@"%d",index]];
                
                // 内容视图
                
                UIView<CQContentViewProtocol> *contentView = cell.contentView;
                
                if (contentView) {
                    
                    [_scrollViewInner addSubview:contentView];
                    
                    contentView.translatesAutoresizingMaskIntoConstraints = NO;
                    
                    NSLayoutConstraint *topMargin = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeTop multiplier:1 constant:0];
                    NSLayoutConstraint *leftMargin = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeLeft multiplier:1 constant:0];
                    NSLayoutConstraint *bottomMargin = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
                    NSLayoutConstraint *rightMargin = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeRight multiplier:1 constant:0];
                    [self addConstraint:topMargin];
                    [self addConstraint:leftMargin];
                    [self addConstraint:bottomMargin];
                    [self addConstraint:rightMargin];
                }
                
                // navigationBar
                
                UIView<CQNavigationBarProtocol> *navigationBar = cell.navigationBar;
                if (navigationBar) {
                    
                    [_scrollViewInner addSubview:navigationBar];
                    
                    navigationBar.translatesAutoresizingMaskIntoConstraints = NO;
                    NSDictionary *views = NSDictionaryOfVariableBindings(navigationBar);
                    
                    [_scrollViewInner addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[navigationBar(64)]" options:nil metrics:nil views:views]];
                    
                    
                    CGFloat top = _controlsHidden ? -64 : 0;
                    NSLayoutConstraint *topMargin = [NSLayoutConstraint constraintWithItem:navigationBar attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:top];
                    [self addConstraint:topMargin];
                    [_topMarginNavDic setObject:topMargin forKey:[NSString stringWithFormat:@"%d",index]];
                    
                    [self addConstraint:[NSLayoutConstraint constraintWithItem:navigationBar attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];
                    
                    CGFloat leftMargin;
                    if ([_dataSource respondsToSelector:@selector(widthForHorizontalView:)]) {
                        leftMargin = [_dataSource widthForHorizontalView:self] * index;
                    }
                    NSLayoutConstraint *leftMarginC = [NSLayoutConstraint constraintWithItem:navigationBar  attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_scrollViewInner attribute:NSLayoutAttributeLeft multiplier:1 constant:leftMargin];
                    
                    [_scrollViewInner addConstraint:leftMarginC];
                    
                    [_leftMarginNavDic setObject:leftMarginC forKey:[NSString stringWithFormat:@"%d",index]];
                }
                
                // toolBar
                
                UIView<CQToolBarProtocol> *toolBar = cell.toolBar;
                if (toolBar) {
                    
                    [_scrollViewInner addSubview:toolBar];
                    
                    toolBar.translatesAutoresizingMaskIntoConstraints = NO;
                    NSDictionary *views = NSDictionaryOfVariableBindings(toolBar);
                    [_scrollViewInner addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[toolBar(64)]" options:nil metrics:nil views:views]];
                    
                    CGFloat bottom = _controlsHidden ? 64 : 0;
                    NSLayoutConstraint *bottomMargin = [NSLayoutConstraint constraintWithItem:toolBar attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:bottom];
                    [self addConstraint:bottomMargin];
                    [_bottomMarginToolDic setObject:bottomMargin forKey:[NSString stringWithFormat:@"%d",index]];
                    
                    [self addConstraint:[NSLayoutConstraint constraintWithItem:toolBar attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];
                    
                    CGFloat leftMargin;
                    if ([_dataSource respondsToSelector:@selector(widthForHorizontalView:)]) {
                        leftMargin = [_dataSource widthForHorizontalView:self] * index;
                    }
                    NSLayoutConstraint *leftMarginC = [NSLayoutConstraint constraintWithItem:toolBar attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_scrollViewInner attribute:NSLayoutAttributeLeft multiplier:1 constant:leftMargin];
                    
                    [_scrollViewInner addConstraint:leftMarginC];
                    
                    [_leftMarginToolDic setObject:leftMarginC forKey:[NSString stringWithFormat:@"%d",index]];
                }
            }
            
        }
    }
    return cell;
}

// 设置重用

- (void)removeCellToReUse {
    
    // cell
    
    NSMutableArray *tempArray = [NSMutableArray array];
    for (UIView<CQHorizontalViewCellProtocol> * cell in self.horizontalViewCells) {
        // 判断某个view的页数与当前页数相差值为2的话，那么让这个view从视图上移除
        if (abs((int)cell.index - (int)_currentPage) == 2){
            [tempArray addObject:cell];
            cell.navigationBar = nil;
            cell.toolBar = nil;
            cell.contentView = nil;
            [cell removeFromSuperview];
        
            [_leftMarginDic removeObjectForKey:[NSString stringWithFormat:@"%d",cell.index]];
            [_leftMarginNavDic removeObjectForKey:[NSString stringWithFormat:@"%d",cell.index]];
            [_leftMarginToolDic removeObjectForKey:[NSString stringWithFormat:@"%d",cell.index]];
            UIView *leftView = [_cellLeftPlaceholderViewDic objectForKey:[NSString stringWithFormat:@"%d",cell.index]];
            [leftView removeFromSuperview];
            [_cellLeftPlaceholderViewDic removeObjectForKey:[NSString stringWithFormat:@"%d",cell.index]];
            [_readyToUseHorizontalViewCells addObject:cell];
        }
    }
    [self.horizontalViewCells removeObjectsInArray:tempArray];
}

// 翻页

- (void)setCurrentPage:(NSInteger)currentPage {
    if (_currentPage == currentPage) {
        return;
    }
    
    NSUInteger oldValue = _currentPage;
    _currentPage = currentPage;
    
    NSInteger numberOfViews = 0;
    if ([_dataSource respondsToSelector:@selector(numberOfCellsInHorizontalView:)]) {
        
        numberOfViews = [_dataSource numberOfCellsInHorizontalView:self];
    }
    
    // 如果新值大于旧值
    if (currentPage > oldValue) {
        // 往右滑，设置右边的视图
        if (currentPage + 1 < numberOfViews) {
            [self setCellForIndex:currentPage + 1];
        }
    }else {
        // 往左滑，设置左边的视图
        if (currentPage > 0) {
            [self setCellForIndex:currentPage - 1];
        }
    }
    
}

// 清空

- (void)clear {
    
    // 清空子视图
    for (UIView<CQHorizontalViewCellProtocol> *cell in _scrollViewInner.subviews) {
        [cell removeFromSuperview];
    }
    
    // 清空数组
    _horizontalViewCells = [NSMutableArray array];
    _readyToUseHorizontalViewCells = [NSMutableArray array];
    _leftMarginDic = [NSMutableDictionary dictionary];
    _leftMarginNavDic = [NSMutableDictionary dictionary];
    _leftMarginToolDic = [NSMutableDictionary dictionary];
    _topMarginNavDic = [NSMutableDictionary dictionary];
    _bottomMarginToolDic = [NSMutableDictionary dictionary];
    _cellLeftPlaceholderViewDic = [NSMutableDictionary dictionary];
    
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    [self resetTimer];
    
    
    NSMutableArray *marray = [[NSMutableArray alloc] initWithCapacity:0];
    if (self.currentCell.navigationBar) {
        [marray addObject:self.currentCell.navigationBar];
    }
    
    if (self.currentCell.toolBar) {
        [marray addObject:self.currentCell.toolBar];
    }
    return ![marray containsObject:touch.view]
    && ![marray containsObject:touch.view.superview];
}

- (void)resetTimer {
    [self.timer invalidate];
    if (!self.currentCell.toolBar.scrubbing) {
        __weak typeof(self) weakSelf = self;
        self.timer = [NSTimer scheduledTimerWithTimeInterval:3.0 firing:^{
            if (weakSelf.timer.isValid && !weakSelf.controlsHidden) {
                [weakSelf toggleControls];
            }
        }];
    }
}

- (void)handleLongPress:(UILongPressGestureRecognizer *)recognizer {
    //长按的时候，设置不透明度为0.7
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        
        if (_longPressClick) {
            
            _longPressClick();
        }
    }else if (recognizer.state == UIGestureRecognizerStateEnded){
        // do something
    }
}

- (IBAction)toggleControls {
    
    if (_singleClick) {
        _singleClick();
    }
    
    [UIView animateWithDuration:0.35 animations:^{
        
        for (NSLayoutConstraint *topC in self->_topMarginNavDic.allValues) {
            
            if (self.controlsHidden) {
                
                topC.constant = 0;
            } else {
                
                topC.constant = -64;
            }
        }
        for (NSLayoutConstraint *bottomC in self->_bottomMarginToolDic.allValues) {
            
            if (self.controlsHidden) {
                
                bottomC.constant = 0;
            } else {
                
                bottomC.constant = 64;
            }
        }
        [self layoutIfNeeded];
        self.controlsHidden = !self.controlsHidden;
    }];
}

- (id<CQHorizontalViewCellProtocol>)currentCell {
    
    id<CQHorizontalViewCellProtocol> currentCell = [[_horizontalViewCells filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"index == %d", _currentPage]] firstObject];
    return currentCell;
}

#pragma mark - 外部方法

- (void)reloadData {
    
    // 清空
    [self clear];
    
    // 计算 scrollView 的 contentSize
    NSInteger numberOfCells = [self resetScrollViewInnerWidth];
    
    // 设置中间子视图
    [self setCellForIndex:_currentPage];
    
    // 设置offsetX
    NSLayoutConstraint *leftMarginC = [_leftMarginDic objectForKey:[NSString stringWithFormat:@"%d",_currentPage]];
    [_scrollView setContentOffset:CGPointMake(leftMarginC.constant, 0)];
    
    // 设置左边
    if (_currentPage != 0 && numberOfCells > 1) {
        
        [self setCellForIndex:_currentPage - 1];
    }
    
    // 设置右边
    if (_currentPage < numberOfCells - 1) {
        
        [self setCellForIndex:_currentPage + 1];
    }
}

- (void)show {
    
    // 添加到 window 上
    [[UIApplication sharedApplication].keyWindow addSubview:self];
    
    // 刷新
    [self reloadData];
    
    self.alpha = 0;
    self.backgroundColor = [UIColor clearColor];
    [UIView animateWithDuration:0.25 animations:^{
        
        self.backgroundColor = [UIColor blackColor];
        self.alpha = 1;
    } completion:^(BOOL finished) {
        
        
    }];
}

- (void)hide {
    
    self.alpha = 1;
    self.backgroundColor = [UIColor blackColor];
    [UIView animateWithDuration:0.25 animations:^{
        
        self.backgroundColor = [UIColor clearColor];
        self.alpha = 0;
    } completion:^(BOOL finished) {
        
        [self removeFromSuperview];
    }];
}

- (UIView<CQHorizontalViewCellProtocol> *)dequeueReusableCellWithIdentifier:(NSString *)identifier {
    
    UIView<CQHorizontalViewCellProtocol> * cell;
    
    NSArray<UIView<CQHorizontalViewCellProtocol> *> *readyToUseHorizontalViewCellByFilter = [_readyToUseHorizontalViewCells filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"reuseIdentifier MATCHES %@", identifier]];
    
    if (readyToUseHorizontalViewCellByFilter.count == 0) {
        
        return nil;
    }else {
        
        cell = [readyToUseHorizontalViewCellByFilter firstObject];
        [_readyToUseHorizontalViewCells removeObject:cell];
    }
    return cell;
}


#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
//    NSLog(@"%f",scrollView.contentOffset.x);
//    NSLog(@"%f",scrollView.frame.size.width);
    CGFloat width = scrollView.frame.size.width;
    if ([_dataSource respondsToSelector:@selector(widthForHorizontalView:)]) {
        width = [_dataSource widthForHorizontalView:self];
    }
    if (width == _oldWidth) {
        
        NSUInteger page = (scrollView.contentOffset.x / width + 0.5);
        self.currentPage = page;
    }
    _oldWidth = width;
}

@end
